package sseGameApps.controller;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;

import net.arnx.jsonic.JSON;

import org.slim3.controller.Controller;
import org.slim3.util.ThrowableUtil;

/**
 * JSON/JSONPレスポンスを返すメソッドを持つController.
 *
 * @author Kenichiro Murata
 */
public abstract class JsonController extends Controller {

    /**
     * JSON/JSONPレスポンスを返すメソッド.
     * runから呼び出した後、runメソッドではnullをreturnする.
     *
     * @param data
     */
    protected void toJson(Object data) {
        // エンコーディングを取得する
        String encoding = request.getCharacterEncoding();
        if (encoding == null) {
            encoding = "UTF-8";
        }

        // JSON形式にエンコード
        String script = JSON.encode(data);
        // コールバックメソッドの指定がある場合はJSONP形式に変換する
        String callback = param("callback");
        if (callback != null) {
            final StringBuilder builder =
                new StringBuilder(script.length() + callback.length() + 10);
            builder.append(callback);
            builder.append("(");
            builder.append(script);
            builder.append(");");
            script = builder.toString();
        }

        // ContentTypeを設定する。
        final StringBuilder builder = new StringBuilder(38);
        builder.append("application/");
        if (callback != null) {
            builder.append("javascript");
        } else {
            builder.append("json");
        }
        builder.append("; charset=");
        builder.append(encoding);
        response.setContentType(builder.toString());

        // レスポンスに書き込む
        try {
            PrintWriter out = null;
            try {
                out =
                    new PrintWriter(new OutputStreamWriter(response
                        .getOutputStream(), encoding));
                out.print(script);
            } finally {
                if (out != null) {
                    out.close();
                }
            }
        } catch (IOException e) {
            ThrowableUtil.wrapAndThrow(e);
        }
    }
}